package com.sec.android.app.myfiles.util.securefolder;

import android.content.Context;
import android.os.Environment;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;

import com.sec.android.app.myfiles.common.Configs;

import java.io.File;
import java.io.IOException;

public class HideUtilsV2 {

    private static final String TAG = HideUtilsV2.class.getSimpleName();

    private static HideUtilsV2 hideUtilsInstance;

    private static Context context;

    public static HideUtilsV2 getInstance(Context c) {
        if (null == hideUtilsInstance) {
            hideUtilsInstance = new HideUtilsV2();
            context = c;
        }
        return hideUtilsInstance;
    }

    private boolean isEmptyFolder(File file) {
        boolean isEmptyFolder = false;
        if (file != null && file.isDirectory()) {
            String[] childFiles = file.list();
            if (childFiles == null || childFiles.length == 0) {
                isEmptyFolder = true;
            }
        }

        return isEmptyFolder;
    }

    //TODO 使用listFiles() 和 list() 得到的实际结果一样吗（除了形式的不同以外）
    //list() 返回的结果里 不包含已有的父目录
    //比如 /1/2/ 获取它的list，会得到 /2 而不是 /1/2


    //当前算法情况：
    //1. 单个文件 --> OK
    //2. 单个空文件夹  --> OK
    //3. 非空文件夹   /1/2  移动 /1 文件夹
    //4. 非空文件夹   /1/2.jpg  移动 /1/2.jpg  -->  如果 /1 目录在目标文件夹里存在，则可以正常移动，否则不能。

    //renameTo 规律:  如果要移动的文件的 父目录 在目标文件夹里存在，则可以正常移动，否则不能。



    //算法过程：
    //1. 遍历目录内的所有子目录和文件，只处理叶子节点（文件 或者 空目录），把文件移动到目标目录（加上.hide)
    public void moveToPrivateFolder(@NonNull File oldFile) {
        Log.i(TAG, "moveToPrivateFolder begin: file is " + oldFile.getAbsolutePath() + ", isFile ? " + oldFile.isFile() + ", isEmptyFolder ? " + isEmptyFolder(oldFile));

        //遍历所有子目录
        if (oldFile.isFile() || isEmptyFolder(oldFile)) {
            //递归出口
            String newFilePath = oldFile.getAbsolutePath().replace(SecureConstants.externalStorageAbsolutePath, SecureConstants.privateRecoveryRootPath);
            //TODO 对文件应该加上 .hide 后缀
            Log.i(TAG, "moveToPrivateFolder. newFilePath is " + newFilePath);
            File newFile = new File(newFilePath);
            if (! newFile.exists()) {
                Log.i(TAG, "moveToPrivateFolderInternal. newFilePath not exist.");

                //TODO 判断newFile 的父目录在目标文件夹里是否存在，如果不存在先创建一个
                File parentFile = newFile.getParentFile();
                if (parentFile.exists()) {
                    Log.i(TAG, "parentFile: " + parentFile.getAbsolutePath() + " exist.");
                } else {
                    Log.i(TAG, "parentFile: " + parentFile.getAbsolutePath() + " not exist. ");
                    parentFile.mkdirs();
                }

                boolean result = oldFile.renameTo(newFile);
                Log.i(TAG, "renameTo result is " + result);
            } else {
                Log.i(TAG, "moveToPrivateFolder. newFilePath already exist！！！");
                //TODO 目标文件已存在
                if (Configs.DELETE_EXISTING_DESTINATION_FILE) {
                    //先删除目标文件夹里已存在的文件 再进行移动
                    newFile.delete();
                    boolean result = oldFile.renameTo(newFile);
                    Log.i(TAG, "renameTo result is " + result);
                }
            }
        } else {
            //说明不是叶子节点
            File[] childFiles = oldFile.listFiles();
            if (childFiles != null && childFiles.length > 0) {
                Log.i(TAG, "childFiles length is " + childFiles.length);
                for (File childFile : childFiles) {
                    moveToPrivateFolder(childFile);
                }
            } else {
                Log.i(TAG, "childFiles length is 0");
            }

            //check oldFile is empty or not
            if (oldFile != null && oldFile.isDirectory()) {
                File[] childFileList = oldFile.listFiles();
                Log.i(TAG, "check empty finally " + oldFile.getAbsolutePath() + " childFiles length is " + childFiles.length);
                if (childFileList == null || childFileList.length == 0) {
                    oldFile.delete();
                }
            }
        }
    }

    public void removeFromPrivateFolder(@NonNull File oldFile) {
        Log.i(TAG, "removeFromPrivateFolder begin: file is " + oldFile.getAbsolutePath() + ", isFile ? " + oldFile.isFile() + ", isEmptyFolder ? " + isEmptyFolder(oldFile));

        //遍历所有子目录
        if (oldFile.isFile() || isEmptyFolder(oldFile)) {
            //递归出口
            String newFilePath = oldFile.getAbsolutePath().replace(SecureConstants.privateRecoveryRootPath, SecureConstants.externalStorageAbsolutePath);
            //TODO 对文件应该加上 .hide 后缀
            Log.i(TAG, "removeFromPrivateFolder. newFilePath is " + newFilePath);
            File newFile = new File(newFilePath);
            if (! newFile.exists()) {
                Log.i(TAG, "removeFromPrivateFolder. newFilePath not exist.");

                //TODO 判断newFile 的父目录在目标文件夹里是否存在，如果不存在先创建一个
                File parentFile = newFile.getParentFile();
                if (parentFile.exists()) {
                    Log.i(TAG, "parentFile: " + parentFile.getAbsolutePath() + " exist.");
                } else {
                    Log.i(TAG, "parentFile: " + parentFile.getAbsolutePath() + " not exist. ");
                    parentFile.mkdirs();
                }

                boolean result = oldFile.renameTo(newFile);
                Log.i(TAG, "renameTo result is " + result);
            } else {
                Log.i(TAG, "removeFromPrivateFolder. newFilePath already exist！！！");
                //TODO 目标文件已存在
                if (Configs.DELETE_EXISTING_DESTINATION_FILE) {
                    //先删除目标文件夹里已存在的文件 再进行移动
                    newFile.delete();
                    boolean result = oldFile.renameTo(newFile);
                    Log.i(TAG, "renameTo result is " + result);
                }
            }
        } else {
            //说明不是叶子节点
            File[] childFiles = oldFile.listFiles();
            if (childFiles != null && childFiles.length > 0) {
                Log.i(TAG, "childFiles length is " + childFiles.length);
                for (File childFile : childFiles) {
                    removeFromPrivateFolder(childFile);
                }
            } else {
                Log.i(TAG, "childFiles length is 0");
            }

            //check oldFile is empty or not
            if (oldFile != null && oldFile.isDirectory()) {
                File[] childFileList = oldFile.listFiles();
                Log.i(TAG, "check empty finally " + oldFile.getAbsolutePath() + " childFiles length is " + childFiles.length);
                if (childFileList == null || childFileList.length == 0) {
                    oldFile.delete();
                }
            }
        }
    }

    private String getHideSuffixPath(@NonNull String filePath, String headerPath, boolean removeHide) {
        String hideSuffixPath = filePath;
        Log.i(TAG, "getHideSuffixPath. previous path is " + filePath);
        StringBuilder combindedPath = new StringBuilder();
        if (filePath != null && filePath.length() > 0) {
            filePath = filePath.replaceFirst(headerPath, "");
            Log.i(TAG, "getHideSuffixPath. after remove private recovery path. path is: " + filePath);

            String[] pathSegments = filePath.split("/");
            Log.i(TAG, "pathSegments length is " + pathSegments.length);
            if (pathSegments != null && pathSegments.length > 0) {
                for (int i = 0; i < pathSegments.length; i++) {
                    Log.i(TAG, "pathSegment" + i + " is " + pathSegments[i]);
                    if (!TextUtils.isEmpty(pathSegments[i])) {
                        combindedPath.append("/");
                        if (removeHide) {
                            int hideIndex = pathSegments[i].lastIndexOf(".hide");
                            if (hideIndex > 0) {
                                combindedPath.append(pathSegments[i].substring(0, hideIndex - 1));
                            }
                        } else {
                            combindedPath.append(pathSegments[i] + ".hide");
                        }
                    }
                }
            }
        }
        return (SecureConstants.privateRecoveryRootPath + combindedPath);
    }

    private void hideFileInternal(File oldFile, File newFile) {
        if (oldFile != null && oldFile.exists()) {
            boolean renameResult = oldFile.renameTo(newFile);
            if (! renameResult) {
                //直接调用renameTo api失败，要处理failed case
                Log.e(TAG, "call renameTo failed... srcFile: " + oldFile.getAbsolutePath() + ", destFile: " + newFile.getAbsolutePath());
                File targetParentFile = newFile.getParentFile();
                Log.i(TAG, "parent of target is : " + targetParentFile.getAbsolutePath());
                if (! targetParentFile.exists()) {
                    Log.i(TAG, "parent not exist. mkdirs and then renameTo again.");
                    targetParentFile.mkdirs();
                    boolean newRenameResult = oldFile.renameTo(newFile);
                    if (newRenameResult) {
                        Log.i(TAG, "yeah... renameTo succeed.");
                    } else {
                        Log.e(TAG, "renameTo failed again...");
                    }
                } else {
                    Log.i(TAG, "parent exist. skip.");
                }
            }
        }
    }
}
